import asyncio
import logging
import time
from datetime import datetime
from typing import List, Dict
from collections import defaultdict

from longport.openapi import TradeContext

from config import config
from market_data import MarketDataProcessor
from signals import SignalGenerator
from order_manager import OrderManager, RiskConfig

logger = logging.getLogger("StrategyEngine")


class TradingEngine:
    def __init__(self, symbols: List[str]):
        self.symbols = symbols
        self.data_processor = MarketDataProcessor(symbols)
        trade_ctx = TradeContext(config)

        # 风险配置
        risk_config = RiskConfig(
            risk_per_trade=0.01,
            max_daily_risk=0.03,
            position_ratio=0.1,
            slippage_ratio=0.001,
            commission_ratio=0.0002,
            order_timeout=10
        )

        # 创建订单管理器
        self.order_mgr = OrderManager(trade_ctx, risk_config)
        # self.order_manager = OrderManager()
        self.signal_generator = SignalGenerator(
            {
                'ema_period': 20,
                'rsi_period': 14,
                'adx_threshold': 25,
                'rsi_overbought': 70,
                'rsi_oversold': 30
            }, self.order_mgr.positions
        )

        # 事件驱动相关
        self.event_queues: Dict[str, asyncio.Queue] = {
            sym: asyncio.Queue(maxsize=100) for sym in symbols
        }
        self._register_data_callbacks()

        # 线程安全的状态管理
        self.trade_count = defaultdict(int)
        self.trade_lock = asyncio.Lock()
        self.semaphore = asyncio.Semaphore(10)  # 控制最大并发数

        # 添加背压控制
        self.backpressure_semaphore = asyncio.Semaphore(100)  # 最大待处理事件数

    def _register_data_callbacks(self):
        """注册数据更新回调"""
        for symbol in self.symbols:
            self.data_processor.register_indicators_updated_callback(
                symbol,
                lambda data, sym=symbol: self._on_indicators_updated(data, sym)
            )

    async def _on_indicators_updated(self,  indicators: dict, symbol: str):
        # print(f"_on_indicators_updated")
        # print(f"type of macd_hist is {type(indicators['macd_hist'])}")
        """带背压控制的事件入队"""
        async with self.backpressure_semaphore:
            # print(f"{symbol}")
            # print(f"信号更新: {indicators}")
            """指标更新事件处理"""
            await self.event_queues[symbol].put({
                'type': 'INDICATORS_UPDATE',
                'symbol': symbol,
                'data': indicators,
                'timestamp': datetime.now()
            })

    async def run(self):
        """事件驱动主循环"""
        # 启动事件处理协程
        handlers = [
            self._event_handler(symbol)
            for symbol in self.symbols
        ]
        await asyncio.gather(*handlers)

    async def _event_handler(self, symbol: str):
        """单个标的的事件处理协程"""
        while True:
            event = await self.event_queues[symbol].get()
            try:
                if event['type'] == 'INDICATORS_UPDATE':
                    await self._process_signal(symbol, event['data'])
            except Exception as e:
                logger.error(f"处理事件失败: {event}", exc_info=True)
            finally:
                self.event_queues[symbol].task_done()

    async def _process_signal(self, symbol: str, indicators: dict):
        """信号处理核心逻辑"""
        # if self.trade_count[symbol] >= config.max_trades:
        #     return

        # 添加指标预处理
        processed_indicators = self._preprocess_indicators(indicators)
        # print(f"type of macd_hist is {type(indicators['macd_hist'])}")

        signal = self.signal_generator.generate_signal(processed_indicators)
        if not signal:
            return

        # print(f"{symbol} {datetime.now()}」信号: {signal}")

        price = self.data_processor.last_prices[symbol]
        await self._execute_trade(symbol, signal, price)
        # self.trade_count[symbol] += 1

    def _preprocess_indicators(self, raw_indicators: dict) -> dict:
        """指标数据预处理"""
        return {
            # 'ema_fast': raw_indicators['ema_fast'],
            'ema': raw_indicators['ema_fast'],
            'ema_slow': raw_indicators['ema_slow'],
            'rsi': raw_indicators['rsi'],
            'macd': raw_indicators['macd'],
            'macd_signal': raw_indicators['macd_signal'],
            'macd_hist': raw_indicators['macd_hist'],
            'atr': raw_indicators['atr'],
            'adx': raw_indicators['adx'],
            'bb_width': raw_indicators['bb_width'],
            'obv': raw_indicators['obv'],
            'obv_ma20': raw_indicators['obv_ma20'],
            'vwap': raw_indicators['vwap'],
            'close': raw_indicators['close'],
            # 'close': raw_indicators['close_history']  # 保留最近100个收盘价
        }

    # async def _process_single_symbol(self, symbol: str):
    #     """处理单个股票信号（带并发控制）"""
    #     async with self.semaphore:
    #         try:
    #             # # 检查交易次数限制
    #             # async with self.trade_lock:
    #             #     if self.trade_count[symbol] >= config.max_trades:
    #             #         return
    #
    #             # 生成交易信号
    #             signal = self.signal_generator.generate_signal(symbol)
    #             if not signal:
    #                 return
    #
    #             # 获取当前价格
    #             current_price = self._get_current_price(symbol)
    #             if not current_price:
    #                 return
    #
    #             # 执行交易
    #             await self._execute_trade(symbol, signal, current_price)
    #
    #             # 更新交易计数
    #             async with self.trade_lock:
    #                 self.trade_count[symbol] += 1
    #                 logger.debug(f"{symbol} 交易计数更新: {self.trade_count[symbol]}")
    #
    #         except Exception as e:
    #             logger.error(f"处理{symbol}时发生异常: {str(e)}", exc_info=True)

    async def _execute_trade(self, symbol: str, signal: str, price: float):
        """执行交易（带并发安全）"""
        # position = self.order_manager.positions.get(symbol)
        # logger.info(f"{symbol} 信号: {signal} 当前持仓: {position}")

        try:
            # 根据信号类型处理
            if signal.startswith("CLOSE"):
                await self._handle_close_signal(symbol, signal, price)
            else:
                await self._handle_open_signal(symbol, signal, price)
        except Exception as e:
            logger.error(f"执行交易失败: {symbol} {signal}", exc_info=True)

    async def _handle_open_signal(self, symbol: str, signal: str, price: float):
        """处理开仓信号"""
        position = await self.order_manager.get_position(symbol)

        if signal == "LONG" and position.confirmed_long == 0 and position.pending_long == 0:
            await self.order_manager.execute_signal(
                signal_type="LONG",
                symbol=symbol,
                entry_price=price
                # reason="趋势开多仓"
            )
        if signal == "LONG" and position.confirmed_short > 0:
            await self.order_manager.execute_signal(
                signal_type="LONG",
                symbol=symbol,
                entry_price=price,
                quantity=position.confirmed_short,
                # reason="平空仓"
            )
        if signal == "SHORT" and position.short == 0 and position.pending_short == 0:
            await self.order_manager.execute_signal(
                signal_type="SHORT",
                symbol=symbol,
                entry_price=price
                # reason="趋势开空仓"
            )

        if signal == "SHORT" and position.confirmed_long > 0:
            await self.order_manager.execute_signal(
                signal_type="SHORT",
                symbol=symbol,
                entry_price=price,
                quantity=position.confirmed_long,
                # reason="平多仓"
            )


    async def _handle_close_signal(self, symbol: str, signal: str, price: float):
        """处理平仓信号"""
        position = await self.order_manager.get_position(symbol)

        if "LONG" in signal and position.long > 0:
            await self.order_manager.execute_order(
                symbol,
                "SELL",
                price,
                quantity=position.long
                # reason="趋势平多仓"
            )
        elif "SHORT" in signal and position.short > 0:
            await self.order_manager.execute_order(
                symbol,
                "BUY",
                price,
                quantity=position.short
                # reason="趋势平空仓"
            )

    def _get_current_price(self, symbol: str) -> float:
        """获取最新价格（带容错）"""
        try:
            return self.data_processor.last_prices[symbol]
        except KeyError:
            logger.warning(f"无法获取{symbol}的当前价格")
            return 0.0

    @staticmethod
    def _is_trading_time() -> bool:
        """交易时间检查（优化版）"""
        # 实际实现需根据时区处理
        return True  # 示例代码